#include "stdio.h"
#include "stdlib.h"

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include "misc.h"
#include "common.h"
#include "delay.h"
#include "uart.h"

#include "led.h"

#if defined(MICROLIB_MODE) || defined(NO_SEMIHOSTING)
#include "stdio.h"
#endif

#ifdef NO_SEMIHOSTING				 //不使用半主机模式
#pragma import(__use_no_semihosting) //通知编译器不要从C库链接时使用带有半主机semihosting的函数

void _sys_exit(int x)
{
	x = x;
}

struct __FILE
{
	int handle;
};
FILE __stdout;
#endif

#if defined(MICROLIB_MODE) || defined(NO_SEMIHOSTING) //直接使用系统自带的库
int fputc(int ch, FILE *f)
{
	USART_ClearFlag(USART1, USART_FLAG_TC); //每次发送数据之前，先清除uart发送完成标记TC，防止意外发生，如接收不到第一字符
	//发送之前给一定的时延
	delay_us(100);
	USART_SendData(USART1, (u16)ch);
	while (!USART_GetFlagStatus(USART1, USART_FLAG_TC))
		; //等待串口的上一次数据发送完毕
	return ch;
}
#else //使用自定义的函数

#endif

/*

*/
void uart_nvic_config(UART_NAME uart)
{
	NVIC_InitTypeDef uart_nvic;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	switch (uart)
	{
	case UART1:
		uart_nvic.NVIC_IRQChannel = USART1_IRQn;
		break;
	case UART2:
		uart_nvic.NVIC_IRQChannel = USART2_IRQn;
		break;
	default:
		break;
	}

	uart_nvic.NVIC_IRQChannelSubPriority = 1;
	uart_nvic.NVIC_IRQChannelPreemptionPriority = 1;
	uart_nvic.NVIC_IRQChannelCmd = ENABLE;

	NVIC_Init(&uart_nvic);
}

void uart_init(MODE mode, UART_NAME uart, uint32_t br)
{
	GPIO_InitTypeDef tx, rx;
	USART_InitTypeDef usart;

	tx.GPIO_Mode = GPIO_Mode_AF_PP;
	tx.GPIO_Speed = GPIO_Speed_50MHz;

	rx.GPIO_Mode = GPIO_Mode_IN_FLOATING;

	//usart 参数配置
	usart.USART_BaudRate = br;										  //波特率
	usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //串口硬件流设置
	usart.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;				  //串口收发模式使能
	usart.USART_Parity = USART_Parity_No;							  //校验位
	usart.USART_StopBits = USART_StopBits_1;						  //停止位
	usart.USART_WordLength = USART_WordLength_8b;					  //字节长度

	switch (uart)
	{
	case UART1:
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //打开串口时钟
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //打开GPIO口时钟

		//tx pa9
		tx.GPIO_Pin = GPIO_Pin_9;
		GPIO_Init(GPIOA, &tx); //tx初始化
		//rx pa10
		rx.GPIO_Pin = GPIO_Pin_10;
		GPIO_Init(GPIOA, &rx);		//rx初始化
		USART_Init(USART1, &usart); //串口参数初始化
		USART_Cmd(USART1, ENABLE);	//串口使能
		if (INTERRUPT == mode)
		{
			USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
			uart_nvic_config(UART1);
		}
		break;
	case UART2:
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //打开串口时钟
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //打开GPIO口时钟

		//tx pa2
		tx.GPIO_Pin = GPIO_Pin_2;
		GPIO_Init(GPIOA, &tx); //tx初始化
		//rx pa3
		rx.GPIO_Pin = GPIO_Pin_3;
		GPIO_Init(GPIOA, &rx);		//rx初始化
		USART_Init(USART2, &usart); //串口参数初始化
		USART_Cmd(USART2, ENABLE);	//串口使能
		if (INTERRUPT == mode)
		{
			USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
			uart_nvic_config(UART2);
		}
		break;
	default:
		break;
	}
}

/*
通过串口发送字符串，并返回发送的长度
*/
u32 uart_send_str(u8 *str)
{
	u32 i = 0;

	while (*(str + i))
	{
		USART_ClearFlag(USART1, USART_FLAG_TC); //每次发送数据之前，先清除uart发送完成标记TC，防止意外发生，如接收不到第一字符
		//发送之前给一定的时延
		delay_ms(1);
		USART_SendData(USART1, *(str + i));
		while (!USART_GetFlagStatus(USART1, USART_FLAG_TC))
			; //等待串口的上一次数据发送完毕
		i++;
	}

	return i;
}

/*
通过串口发送任意内容
*/
void uart_send_data(UART_NAME uart, void *data, u32 len)
{
	u32 i = 0;
	USART_TypeDef *USARTx;

	switch (uart)
	{
	case UART1:
		USARTx = USART1;
		break;
	case UART2:
		USARTx = USART2;
		break;
	default:
		break;
	}
	while (i != len)
	{
		USART_ClearFlag(USARTx, USART_FLAG_TC); //每次发送数据之前，先清除uart发送完成标记TC，防止意外发生，如接收不到第一字符
		//发送之前给一定的时延
		delay_us(10);
		USART_SendData(USARTx, *((char *)data + i));
#ifdef USART_DR_TEST
		if ((USARTx->DR))
		{
			led_opr(REVERSAL);
		}
#endif
		while (!USART_GetFlagStatus(USARTx, USART_FLAG_TC))
			; //等待串口的上一次数据发送完毕
		i++;
	}
}

void uart_send_data_quick(void *data, u32 len)
{
	u32 i = 0;

	while (i != len)
	{
		USART_ClearFlag(USART1, USART_FLAG_TC); //每次发送数据之前，先清除uart发送完成标记TC，防止意外发生，如接收不到第一字符
		//发送之前给一定的时延
		delay_us(10);
		USART_SendData(USART1, *((char *)data + i));
		while (!USART_GetFlagStatus(USART1, USART_FLAG_TC))
			; //等待串口的上一次数据发送完毕
		i++;
	}
}

/*
通过串口接收数据
len：len为串口数据接收的缓存大小（字节数）
设计思路：阻塞或非阻塞
	非阻塞模式：返回实际接收数据个数
*/
u32 uart_recv_data(void *data, u32 len)
{
	u8 *recv_data = data;
	u32 i = 0, j = 0;

	while (i != len)
	{
		if (SET == USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) //检查接收数据寄存器非空标志位
		{
#ifdef USART_DR_TEST
			if ((USART1->DR))
			{
				led_opr(REVERSAL);
			}
#endif
			recv_data[j] = (u8)USART_ReceiveData(USART1);
			j++;
		}
		i++;
	}
	return j;
}

void USART1_IRQHandler(void)
{
	//printf("USART1_IRQHandler\r\n");
	if (SET == USART_GetITStatus(USART1, USART_IT_RXNE))
	{
		USART_SendData(USART1, USART_ReceiveData(USART1));
	}
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}

u8 esp_recv[128]; //缓存
u8 esp_recv_flag = 0;

void USART2_IRQHandler(void)
{
	// static u8 recv_flag = 0;

	//printf("USART2_IRQHandler\r\n");

	if (SET == USART_GetITStatus(USART2, USART_IT_RXNE))
	{
		// USART_SendData(USART2,USART_ReceiveData(USART2));
		//USART_SendData(USART1,USART_ReceiveData(USART2));
		//esp_recv_flag = 1;
		esp_recv[esp_recv_flag++] = USART_ReceiveData(USART2);
		//接收数据的分离问题，缓存模型
		/*
			数据存储模型
				存储大小
				存储方式
		*/
		if (128 < esp_recv_flag)
		{
			esp_recv_flag = 0;
			memset(esp_recv, 0, sizeof(esp_recv));
		}
	}
	USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}
